#ifndef SIGNAL_SLOT_H
#define SIGNAL_SLOT_H

#include "EventLoop.h"
#include <memory>
#include <vector>
#include <functional>
#include <type_traits>

namespace Tool
{

enum class ConnectionType
{
    Direct,   // 同步调用（当前线程立即执行）
    Queued,   // 异步调用（通过事件循环队列执行）
    Auto      // 自动判断（同线程同步，异线程异步）
};

class SlotBase;
struct MemberSlotEvent : Event
{
    std::shared_ptr<SlotBase> slot_base;

    MemberSlotEvent(EventPriority p = EventPriority::Normal)
        : Event(EventType::SignalSlot, p)
    {

    }
};

class Connection;
class SlotBase
{
public:
    virtual ~SlotBase() = default;
    virtual void Call(std::shared_ptr<MemberSlotEvent> event) = 0;  // 调用槽函数
};

template<typename Func>
class Slot : public SlotBase
{
public:
    explicit Slot(Func&& func)
        : m_func(std::forward<Func>(func))
    {

    }
    void Call(std::shared_ptr<MemberSlotEvent> event) override
    {
        m_func(event);
    }

private:
    Func m_func;  // 存储函数对象
};

template<typename Obj, typename MemFunc>
class MemberSlot : public SlotBase
{
public:
    MemberSlot(Obj* obj, MemFunc func)
        : m_obj(obj)
        , m_func(func)
    {

    }

    void Call(std::shared_ptr<MemberSlotEvent> event) override
    {
        (m_obj->*m_func)(event);
    }

private:
    Obj* m_obj;       // 对象指针
    MemFunc m_func;   // 成员函数指针
};

class ExportAPI Signal
{
public:
    explicit Signal(EventLoop* loop)
        : m_loop(loop)
    {

    }
    ~Signal();

    Signal(const Signal&) = delete;
    Signal& operator=(const Signal&) = delete;

    template<typename Func>
    std::shared_ptr<Connection> connect(Func&& func, ConnectionType type)
    {
        auto slot = std::make_shared<Slot<Func>>(std::forward<Func>(func));
        auto conn = std::make_shared<Connection>(this, slot, type, m_loop);

        std::lock_guard<std::mutex> lock(m_mutex);
        m_connections.push_back(conn);
        return conn;
    }

    template<typename Obj, typename Func>
    std::shared_ptr<Connection> connect(Obj* obj, Func&& func, ConnectionType type)
    {
        auto slot = std::make_shared<MemberSlot<Obj, Func>>(obj, std::forward<Func>(func));
        auto conn = std::make_shared<Connection>(this, slot, type, m_loop);

        std::lock_guard<std::mutex> lock(m_mutex);
        m_connections.push_back(conn);
        return conn;
    }

    void emit(std::shared_ptr<MemberSlotEvent> event);

private:
    EventLoop* m_loop;  // 关联的事件循环
    std::vector<std::shared_ptr<Connection>> m_connections;
    std::mutex m_mutex;
};

class ExportAPI Connection : public std::enable_shared_from_this<Connection>
{
public:
    Connection(Signal* signal, std::shared_ptr<SlotBase> slot, ConnectionType type, EventLoop* loop)
        : m_signal(signal)
        , m_slot(std::move(slot))
        , m_type(type), m_loop(loop)
    {

    }

    void invoke(std::shared_ptr<MemberSlotEvent> event);
    void disconnect();

private:
    Signal* m_signal;
    std::shared_ptr<SlotBase> m_slot;
    ConnectionType m_type;
    EventLoop* m_loop;
    std::atomic<bool> m_connected{true};
};

void ExportAPI RegisterSignalSlotEvents(EventLoop* loop);

}  // namespace Tool

#endif  // SIGNAL_SLOT_H
